#pragma once

#include "../common/message.pb.h"
#include "../common/StringHelper.hpp"
#include <iostream>
#include <string>
#include <vector>

/**
 * routingKey：由字母，数字和_组成，由.隔开
 * bindingKey：由字母，数字和_组成，由.隔开，支持通配符*和#
 *   *：匹配任意一个单词（a.*.c <=> a.b.c）
 *   #：匹配任意零个或多个单词（a.#.d <=> a.b.c.d）
*/

namespace micromq
{
    class Router
    {
    public:
        static bool isRoutingKeyValid(const std::string& routingKey)
        {
            for(auto ch : routingKey)
            {
                if(!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || 
                     (ch >= '0' && ch <= '9') || (ch == '.') || (ch == '_'))) 
                {
                    return false;
                }
            }
            return true;
        }

        static bool isBindingKeyValid(const std::string& bindingKey)
        {
            // 判断字符合法
            for(auto ch : bindingKey)
            {
                if(!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || 
                    (ch >= '0' && ch <= '9') || (ch == '.') || (ch == '_') || 
                    (ch == '*') || (ch == '#'))) 
                {
                    return false;
                }
            }
            // *和#只能独立出现，两侧应是.（a.*.b / a.#.b / a.* / a.#）
            std::vector<std::string> words = StringHelper::split(bindingKey, ".");
            for(auto& a : words)
            {
                if(a.size() > 1 && (a.find(".") != std::string::npos || a.find("#") != std::string::npos))
                {
                    return false;
                }
            }
            // #代表匹配任意零个或多个单词，与*或#连续出现还是#，无意义
            for(int i = 1; i < words.size(); i++)
            {
                if((words[i-1] == "#" && words[i] == "#") ||
                    (words[i-1] == "#" && words[i] == "*") ||
                    (words[i-1] == "*" && words[i] == "#"))
                {
                    return false;
                }
            }
            return true;
        }

        static bool route(ExchangeType type, const std::string& bindingKey, const std::string& routingKey)
        {
            if(type == ExchangeType::DIRECT)
            {
                return bindingKey == routingKey;
            }
            else if(type == ExchangeType::FANOUT)
            {
                return true;
            }
            else
            {
                std::vector<std::string> bindings = StringHelper::split(bindingKey, ".");
                std::vector<std::string> routings = StringHelper::split(routingKey, ".");
                int m = bindings.size(); //行数
                int n = routings.size(); //列数
                std::vector<std::vector<bool>> dp(m+1, std::vector<bool>(n+1, false));
                dp[0][0] = true;
                for(int i = 1; i <= m; i++) {
                    if (bindings[i-1] != "#") break;
                    dp[i][0] = true;
                }
                for(int i = 1; i <= m; i++) {
                    for(int j = 1; j <= n; j++) {
                        if(bindings[i-1] == "#") {
                            dp[i][j] = dp[i-1][j-1] || dp[i][j-1] || dp[i-1][j];
                        } else if(bindings[i-1] == "*" || bindings[i-1] == routings[j-1]) {
                            dp[i][j] = dp[i-1][j-1];
                        }
                    }
                }
                return dp[m][n];
            }
        }
    };
}